home *** CD-ROM | disk | FTP | other *** search
- /*
- * text.c
- */
-
- /*
- * mpage: a program to reduce pages of print so that several pages
- * of output appear on one printed sheet.
- *
- * Written by:
- * ...!uunet!\ Mark Hahn, Sr Systems Engineer
- * >pyrdc!mark Pyramid Technology Corporation
- * ...!pyramid!/ Vienna, Va (703)848-2050
- *
- *
- * Copyright (c) 1988 Mark P. Hahn, Herndon, Virginia
- * Copyright (c) 1994-1997 Marcel J.E. Mol, The Netherlands
- * marcel@mesa.nl
- *
- * Permission is granted to anyone to make or distribute verbatim
- * copies of this document as received, in any medium, provided
- * that this copyright notice is preserved, and that the
- * distributor grants the recipient permission for further
- * redistribution as permitted by this notice.
- *
- */
-
- #include "mpage.h"
- #include <sys/types.h> /* Ultrix... Michael Fulbright msf@as.arizona.edu */
- #include <time.h>
- #include <sys/stat.h>
-
- /*
- * keeps track of the current location on the sheet. it is kept global
- * to while file printing process because of form feeds in particular.
- * form feeds change the vertical page location (line number) but not
- * the horizontal location (character column)
- */
- struct pageloc {
- int pl_line;
- int pl_col;
- int pl_new_line;
- int pl_new_col;
- };
-
- static struct pageloc loc;
- static char text[LINESIZE];
-
- static char *file_name;
- static int file_pagenum;
- static char file_date[LINESIZE];
-
- /*
- * Function Declarations
- */
- static int do_text_sheet();
- static int text_onepage();
- static char *mp_get_text();
-
-
- /*
- * do_text_doc processes an input stream fd, reducing output to fit on
- * a printed page as decribed by asheet, and prints this on outfd.
- */
- void
- do_text_doc(fd, asheet, outfd, fname)
- FILE *fd;
- struct sheet *asheet;
- FILE *outfd;
- char * fname;
- {
- struct stat file_stat;
-
- /*
- * initalize the postion on the first printed page
- */
- loc.pl_line = 1;
- loc.pl_col = opt_indent;
- file_name = fname;
- file_pagenum = 0;
- fstat(fileno(fd), &file_stat);
- strftime(file_date, LINESIZE, dateformat, localtime(&file_stat.st_ctime));
-
- /*
- * while we have input, print a page
- */
- do_sheets(do_text_sheet, fd, asheet, outfd );
-
- return;
-
- } /* do_text_doc */
-
-
-
- /*
- * do_text_sheet creates one printed sheet consisting of several reduced pages
- */
- static int
- do_text_sheet(fd, asheet, outfd)
- FILE *fd;
- struct sheet *asheet;
- FILE *outfd;
- {
- int rtn_val = FILE_MORE;
- int peekc;
-
- if ((peekc = getc(fd)) == EOF)
- return FILE_EOF;
- ungetc(peekc, fd);
-
- if (((points->pp_origin_x == 0) && !points->skip) || opt_file) {
- /*
- * keep track of the pages printed
- */
- ps_pagenum++;
- fprintf(outfd, "%%%%Page: %d %d\n", ps_pagenum, ps_pagenum);
- # ifdef DEBUG
- if (Debug_flag & DB_PSMPAGE)
- fprintf(outfd, "(Page: %d\\n) print flush\n", ps_pagenum);
- # endif /* DEBUG */
- fprintf(outfd, "save\n"); /* for better memory usage */
-
- /*
- * Now is the time to print a sheet header...
- * for now, this has to be done before outline...
- */
- sheetheader(outfd, file_name);
-
- /*
- * print the page outline, which draws lines and such
- */
- mp_outline(outfd, asheet);
-
- /*
- * run through the list of base points for putting reduced pages
- * on the printed page
- */
- points = asheet->sh_pagepoints;
- }
- /* while (points->pp_origin_x != 0 && rtn_val == FILE_MORE) {} */
- while ((points->pp_origin_x != 0 || points->skip) && rtn_val == FILE_MORE) {
- /*
- * print one reduced page by moving to the proper point,
- * turning to the proper aspect, scaling to the proper
- * size, and setting up a clip path to prevent overwriting;
- * then` print a reduced page of output.
- */
- int pheight;
-
- file_pagenum++;
-
- if (points->skip) {
- rtn_val = text_onepage(fd, asheet, outfd);
- points++;
- continue;
- }
-
- fprintf(outfd, "gsave\n");
- # ifdef DEBUG
- if (Debug_flag & DB_PSMPAGE) {
- fprintf(outfd, "( %d %d translate %d rotate\\n)",
- points->pp_origin_x(), points->pp_origin_y(),
- asheet->sh_rotate);
- fprintf(outfd, " print flush\n");
- }
- # endif /* DEBUG */
- /*
- * Take position on paper
- */
- fprintf(outfd, "%d %d translate\n",
- points->pp_origin_x(), points->pp_origin_y());
- if (asheet->sh_rotate)
- fprintf(outfd, "%d rotate\n", asheet->sh_rotate);
- /*
- * Clip to logical page
- */
- fprintf(outfd,
- "0 0 moveto 0 %d rlineto %d 0 rlineto 0 %d rlineto closepath clip\n",
- (*asheet->sh_height)(), (*asheet->sh_width)(),
- -(*asheet->sh_height)());
-
- pheight = asheet->sh_plength * fsize +
- (opt_mp_header ? HSIZE + 2 : 0);
- /*
- * Scale to logical page
- */
- fprintf(outfd, "%d %d mp_a_x mul div %d %d div scale\n",
- (*asheet->sh_width)(), asheet->sh_cwidth,
- (*asheet->sh_height)(), pheight);
- /*
- * Draw header bar and print header when needed
- */
- if (opt_mp_header) {
- int pos = (asheet->sh_plength) * fsize;
- fprintf(outfd, "newpath 0 %d moveto %d mp_a_x mul 0 rlineto stroke\n",
- pos, asheet->sh_cwidth);
- pos += 4;
- fprintf(outfd, "headerfont setfont\n");
- if (opt_header != NULL)
- fprintf(outfd, "3 %d moveto (%s) show\n", pos, opt_header);
- else {
- fprintf(outfd, "3 %d moveto (%s) show\n", pos, file_date);
- fprintf(outfd, "%d mp_a_x mul dup (Page %d) stringwidth pop "
- "sub 3 sub %d moveto",
- asheet->sh_cwidth, file_pagenum, pos);
- fprintf(outfd, " (Page %d) show\n", file_pagenum);
- fprintf(outfd, "fnamefont setfont\n");
- fprintf(outfd, "(%s) stringwidth pop sub 2 div %d moveto\n",
- file_name, pos);
- fprintf(outfd, "(%s) show\n", file_name);
- }
- }
-
- /*
- * Take pagemargin and font descenders (fsize/4) into account
- * and scale again
- */
- fprintf(outfd, "%d %d translate %d %d div %d %d div scale\n",
- pagemargin_left, pagemargin_bottom + fsize/4,
- (*asheet->sh_width)() - pagemargin_left - pagemargin_right,
- (*asheet->sh_width)(),
- asheet->sh_plength * fsize - pagemargin_top - pagemargin_bottom,
- asheet->sh_plength * fsize);
-
- fprintf(outfd, "textfont setfont\n");
-
- /*
- * place one reduced page on the printed page
- */
- rtn_val = text_onepage(fd, asheet, outfd);
- /*
- * clean up this page and move to the next
- */
- fprintf(outfd, "grestore\n");
- points++;
- }
- /*
- * release PS vm used, and eject the sheet
- */
- if (points->pp_origin_x == 0 ||
- (rtn_val == FILE_EOF && opt_file)) {
- fprintf(outfd, "restore\n");
- if (had_ps)
- fprintf(outfd, "showsheet\n");
- else
- fprintf(outfd, "showpage\n");
- }
- /*
- * let the upper level know about the status of possible EOF
- */
- return rtn_val;
-
- } /* do_text_sheet */
-
-
-
- /*
- * text_onepage places on page of reduced output on the printed page
- * all scaling, translation, and rotation has already been done before
- */
- static int
- text_onepage(file, asheet, outfd)
- FILE *file;
- struct sheet *asheet;
- FILE *outfd;
- {
- char *text;
-
- /*
- * Start off with printing any wanted annotation
- */
- if (opt_textbox) {
- fprintf(outfd, "%d setlinewidth\n", textbox.thick);
- fprintf(outfd, "%d mp_a_x mul %d moveto 0 %d rlineto\n",
- textbox.over, textbox.lift*fsize, textbox.high*fsize);
- fprintf(outfd, "%d mp_a_x mul 0 rlineto 0 %d rlineto closepath stroke\n",
- textbox.wide, -textbox.high*fsize);
- }
-
- /*
- * as we move from one page to the next, restart printing text at
- * the head of the page. horziontal location is not reset because
- * form feeds leave the column the same from page to page.
- */
- Debug(DB_ONEPAGE, "%% reseting line to top of page\n", 0);
- loc.pl_line = 1;
- /*
- * keep getting lines of input, until we have filled a page
- */
- while (loc.pl_line <= asheet->sh_plength) {
- text = mp_get_text(file, &loc, asheet);
- Debug(DB_ONEPAGE, "%% text = %d\n", text);
- if (text == 0) {
- return FILE_EOF;
- }
- Debug(DB_ONEPAGE, "%% text = (%s)\n", text);
- Debug(DB_ONEPAGE, "%% loc.pl_line = %d\n", loc.pl_line);
- Debug(DB_ONEPAGE, "%% loc.pl_col = %d\n", loc.pl_col);
- Debug(DB_ONEPAGE, "%% loc.pl_new_line = %d\n",loc.pl_new_line);
- Debug(DB_ONEPAGE, "%% loc.pl_new_col = %d\n", loc.pl_new_col);
- if (text[0] != 0 && !points->skip) {
- switch (loc.pl_col) {
- /* fprintf(outfd, "(%s\\n) print flush\n", text); */
- case 0: putc('0', outfd);
- break;
- case 1: fprintf(outfd, "mp_a_x");
- break;
- default: fprintf(outfd, "%d mp_a_x mul", loc.pl_col);
- break;
- }
- fprintf(outfd, " %d moveto (%s) show\n",
- (asheet->sh_plength - loc.pl_line) * fsize,
- text);
- }
- if (loc.pl_new_line == -1) {
- loc.pl_col = loc.pl_new_col;
- return FILE_MORE;
- }
- loc.pl_line = loc.pl_new_line;
- loc.pl_col = loc.pl_new_col;
- }
-
- return FILE_MORE;
-
- } /* text_onepage */
-
-
-
- static char *
- mp_get_text(infile, locp, asheet)
- FILE *infile;
- struct pageloc *locp;
- struct sheet *asheet;
- {
- int gathering;
- int tabcnt;
- int ichr;
- static int prevchar = 0;
- char *textp;
-
- textp = text;
- locp->pl_new_line = locp->pl_line;
- locp->pl_new_col = locp->pl_col;
-
- gathering = 1;
- /*
- * Make sure there is still enough space in text array (we
- * may need to put 5 characters plus NULL in it.
- */
- while (gathering && textp - text < LINESIZE - 5) {
- if (prevchar) {
- ichr = prevchar;
- prevchar = 0;
- }
- else
- ichr = fgetc(infile);
- Debug(DB_GETLINE, "%%called fgetc ichr = %d", ichr);
- Debug(DB_GETLINE, "(%d)\n", EOF);
- /*
- * this prevents nulls in the input from confusing the
- * program logic with truncated strings
- */
- if (ichr == 0) {
- ichr = 1;
- }
- switch (ichr) {
- case EOF:
- gathering = 0;
- return 0;
- /* break; */
- case '\n':
- locp->pl_new_line++;
- locp->pl_new_col = opt_indent;
- gathering = 0;
- break;
- case '\r':
- locp->pl_new_col = opt_indent;
- gathering = 0;
- break;
- case '\b':
- if (--locp->pl_new_col < opt_indent) {
- locp->pl_new_col = opt_indent;
- }
- gathering = 0;
- break;
- case '\f':
- locp->pl_new_line--;
- gathering = 0;
- break;
- case '\t':
- tabcnt = opt_tabstop -
- ((locp->pl_new_col - opt_indent) % opt_tabstop);
- locp->pl_new_col += tabcnt;
- gathering = 0;
- break;
- /*
- * case ' ':
- * locp->pl_new_col++;
- * gathering = 0;
- * break;
- */
- default: /* keep on gathering if it fits on the line ... */
- if (opt_fold &&
- (locp->pl_new_col >= asheet->sh_cwidth)) {
- prevchar = ichr;
- gathering = 0;
- locp->pl_new_line++;
- locp->pl_new_col = opt_indent;
- break;
- }
- if (ichr == ')' || ichr == '(' || ichr == '\\') {
- *textp++ = '\\';
- *textp++ = ichr;
- }
- /* else if (ichr >= ' ' && ichr <= '~') */
- else if (ichr >= first_encoding && ichr <= last_encoding)
- *textp++ = ichr;
- else {
- *textp++ = '\\';
- *textp++ = '2';
- *textp++ = '7';
- *textp++ = '7';
- }
- locp->pl_new_col++;
- break;
- }
- }
- *textp = 0;
- /*
- * remove any spaces at the front of the text string by
- * "converting" it to a position change
- */
- textp = text;
- while (*textp && *textp == ' ') {
- /*
- * this affects the starting position of this text string
- * (not the next)
- */
- locp->pl_col++;
- textp++;
- }
-
- return textp;
-
- } /* mp_get_text */
-
-